#include <mockcpp/mockcpp.hpp>
#include <testngpp/testngpp.hpp>
#include <Length.h>
#include <LengthUnit.h>
#include <iostream>
#include <BaseUnitStreamOutput.h>
#include <LargerUnitStreamOutput.h>

USING_MOCKCPP_NS
USING_TESTNGPP_NS

FIXTURE(Length)
{
	TEST(should be able to compare mile with yard. 1 mile = 1760 yard)
	{
		ASSERT_TRUE(Length(1,MILE) == Length(1760,YARD));
	}

	TEST(should be able to compare yard with feet. 1 yard = 3 feet)
	{
		ASSERT_TRUE(Length(1,YARD) == Length(3,FEET));
	}

	TEST(should be able to compare mile with feet. 1 mile = 1760 * 3 feet)
	{
		ASSERT_TRUE(Length(1, MILE) == Length(1760 * 3, FEET));
	}

    TEST(should be able to fail if mile not equal to yard. 1 mile != 1000 yard)
    {
        ASSERT_TRUE(Length(1,MILE) != Length(1000,YARD));
    }

    TEST(should be able to fail if yard not equal to feet, 1 yard != 100 feet)
    {
        ASSERT_TRUE(Length(1,YARD) != Length(100,FEET));
    }
};

FIXTURE(Add)
{
    TEST(should be able to add yard to feet, 1 yard + 2 feet = 5 feet)
    {
        ASSERT_TRUE(Length(1,YARD) + Length(2,FEET) == Length(5,FEET));
    }
};

FIXTURE(LargerUnitStreamOutput)
{
    std::ostringstream     os;
    LargerUnitStreamOutput outputMethod;

    TEST(should be able to print 2 feet as "2 FEET")
    {
        Length(2, FEET).outputStream(outputMethod, os);
        ASSERT_EQ("2 FEET", os.str());
    }

    TEST(should be able to print 5 feet as "1 YARD 2 FEET")
    {
        Length(5, FEET).outputStream(outputMethod, os);
        ASSERT_EQ("1 YARD 2 FEET", os.str());
    }

    TEST(should be able to print 1781 feet as "1 MILE 21 YARD")
    {
        Length(1781, YARD).outputStream(outputMethod, os);
        ASSERT_EQ("1 MILE 21 YARD", os.str());
    }

    TEST(should be able to print 0 mile as "")
    {
        Length(0, MILE).outputStream(outputMethod, os);
        ASSERT_EQ("", os.str());
    }
};

FIXTURE(BaseUnitStreamOutput)
{
    std::ostringstream os;
    BaseUnitStreamOutput outputMethod;

    TEST(should be able to output 1 MILE as "5280 FEET")
    {
        Length(1, MILE).outputStream(outputMethod, os);
        ASSERT_EQ("5280 FEET", os.str());
    }

    TEST(should be able to output 2 YARD as "6 FEET")
    {
        Length(2, YARD).outputStream(outputMethod, os);
        ASSERT_EQ("6 FEET", os.str());
    }

    TEST(should be able to output 3 FEET as "3 FEET")
    {
        Length(3, FEET).outputStream(outputMethod, os);
        ASSERT_EQ("3 FEET", os.str());
    }

    TEST(should be able to output 0 MILE as "0 FEET")
    {
        Length(0, MILE).outputStream(outputMethod, os);
        ASSERT_EQ("0 FEET", os.str());
    }
};
